package org.dolphin.entity.security;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import org.dolphin.base.constant.DatabaseAttribute;
import org.dolphin.entity.interceptor.Auditable;
import org.dolphin.entity.misc.UserLocale;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.util.ObjectUtils;

@Entity
@Table(name = "MS_USER", uniqueConstraints = {@UniqueConstraint(columnNames = {"USERNAME"}, name = "UQ_MS_USER_USERNAME")})
public class User implements Serializable, Auditable {
  private static final long serialVersionUID = 3100554436248400370L;
  private String id;
  private String username;
  private String password;
  private String firstname;
  private String lastname;
  private String address;
  private String postalCode;
  private Long version;
  private Boolean enabled;
  private Boolean locked;
  private String phone;
  private Date createdDate;
  private Date updatedDate;
  private Integer invalidAuthenticationCount;
  private User createdBy;
  private User updatedBy;
  private List<UserGroup> userGroups;
  private UserLocale userLocale;
  private Boolean administrator;

  @Override
  public boolean equals(Object obj) {
    if (obj == this) {
      return true;
    } else if (obj instanceof User) {
      User oth = (User) obj;
      return ObjectUtils.nullSafeEquals(getId(), oth.getId());
    }
    return false;
  }

  @Column(name = "ADDRESS", nullable = false, length = 500)
  public String getAddress() {
    return address;
  }

  @Column(name = "ADMINISTRATOR", nullable = false)
  public Boolean getAdministrator() {
    return administrator;
  }

  @Override
  @ManyToOne(fetch = FetchType.LAZY, optional = true)
  @JoinColumn(name = "CREATED_BY", nullable = true)
  @ForeignKey(name = "FK_MS_USER_CREATED_BY")
  public User getCreatedBy() {
    return createdBy;
  }

  @Override
  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "CREATED_DATE", nullable = false)
  public Date getCreatedDate() {
    return createdDate;
  }

  @Column(name = "ENABLED", nullable = false)
  public Boolean getEnabled() {
    return enabled;
  }

  @Column(name = "FIRSTNAME", nullable = false, length = 100)
  public String getFirstname() {
    return firstname;
  }

  @Id
  @GeneratedValue(generator = "uuid2")
  @GenericGenerator(name = "uuid2", strategy = "org.dolphin.base.id.generator.CustomUUIDGenerator")
  @Column(name = "ID", nullable = false, length = DatabaseAttribute.ID_LENGTH)
  public String getId() {
    return id;
  }

  @Column(name = "INVALID_AUTH_COUNT", nullable = false)
  public Integer getInvalidAuthenticationCount() {
    return invalidAuthenticationCount;
  }

  @Column(name = "LASTNAME", nullable = false, length = 100)
  public String getLastname() {
    return lastname;
  }

  @Column(name = "LOCKED", nullable = false)
  public Boolean getLocked() {
    return locked;
  }

  @Column(name = "PASSWORD", nullable = false, length = 200)
  public String getPassword() {
    return password;
  }

  @Column(name = "PHONE", nullable = true, length = 20)
  public String getPhone() {
    return phone;
  }

  @Column(name = "POSTAL_CODE", nullable = true, length = 15)
  public String getPostalCode() {
    return postalCode;
  }

  @Override
  @ManyToOne(fetch = FetchType.LAZY, optional = true)
  @JoinColumn(name = "UPDATED_BY", nullable = true)
  @ForeignKey(name = "FK_MS_USER_UPDATED_BY")
  public User getUpdatedBy() {
    return updatedBy;
  }

  @Override
  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "UPDATED_DATE", nullable = true)
  public Date getUpdatedDate() {
    return updatedDate;
  }

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user")
  @Fetch(FetchMode.SUBSELECT)
  @ForeignKey(name = "FK_MS_USER_MS_GROUP_USER")
  public List<UserGroup> getUserGroups() {
    return userGroups;
  }

  @ManyToOne(optional = false, fetch = FetchType.LAZY)
  @JoinColumn(name = "LOCALE_ID", nullable = false)
  @ForeignKey(name = "FK_MS_USER_LOCALE")
  public UserLocale getUserLocale() {
    return userLocale;
  }

  @Column(name = "USERNAME", nullable = false, length = 100)
  public String getUsername() {
    return username;
  }

  @Version
  @Column(name = "VERSION_NO", nullable = false)
  public Long getVersion() {
    return version;
  }

  @Override
  public int hashCode() {
    int hash = ObjectUtils.nullSafeHashCode(getId());
    return hash;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public void setAdministrator(Boolean administrator) {
    this.administrator = administrator;
  }

  @Override
  public void setCreatedBy(User createdBy) {
    this.createdBy = createdBy;
  }

  @Override
  public void setCreatedDate(Date createdDate) {
    this.createdDate = createdDate;
  }

  public void setEnabled(Boolean enabled) {
    this.enabled = enabled;
  }

  public void setFirstname(String firstname) {
    this.firstname = firstname;
  }

  public void setId(String id) {
    this.id = id;
  }

  public void setInvalidAuthenticationCount(Integer invalidAuthenticationCount) {
    this.invalidAuthenticationCount = invalidAuthenticationCount;
  }

  public void setLastname(String lastname) {
    this.lastname = lastname;
  }

  public void setLocked(Boolean locked) {
    this.locked = locked;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public void setPhone(String phone) {
    this.phone = phone;
  }

  public void setPostalCode(String postalCode) {
    this.postalCode = postalCode;
  }

  @Override
  public void setUpdatedBy(User updatedBy) {
    this.updatedBy = updatedBy;
  }

  @Override
  public void setUpdatedDate(Date updatedDate) {
    this.updatedDate = updatedDate;
  }

  public void setUserGroups(List<UserGroup> groups) {
    this.userGroups = groups;
  }

  public void setUserLocale(UserLocale userLocale) {
    this.userLocale = userLocale;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public void setVersion(Long version) {
    this.version = version;
  }
}
